package com.zxp.zxpsmarthomeapk.customview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;

import com.zxp.zxpsmarthomeapk.R;


/**
 * 圆形进度自定义View
 */

public class RoundProgress extends View {

    private static final int MIN_ANIM_OFFSET = 10;

    private Bitmap mBackground = null;
    private Bitmap mProgress = null;
    private Paint mPaint;
    private PorterDuffXfermode mMode;
    private int mStartAngle = 0;
    private int mTotleAngle = 360;
    private float mDstAngle = 190;
    private float mFromAngle = 0;
    private float mCurAngle = 0;

    private ValueAnimator mAnimator = ValueAnimator.ofFloat(1.0f);
    private float animValue = 1.0f;

    public RoundProgress(Context context) {
        super(context);
        initView(context, null, 0);
    }

    public RoundProgress(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs, defStyleAttr);
    }

    private void initView(Context context, AttributeSet attrs, int defStyleAttr) {
        int backResId = 0;
        int progressResId = 0;
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundProgress, defStyleAttr, 0);
        int count = ta.getIndexCount();
        for (int i = 0; i < count; i++) {
            int attr = ta.getIndex(i);
            if (attr == R.styleable.RoundProgress_rpBackground) {
                backResId = ta.getResourceId(attr, 0);
            } else if (attr == R.styleable.RoundProgress_rpProgress) {
                progressResId = ta.getResourceId(attr, 0);
            } else if (attr == R.styleable.RoundProgress_rpStartAngle) {
                mStartAngle = ta.getInt(attr, 0);
            } else if (attr == R.styleable.RoundProgress_rpTotleAngle) {
                mTotleAngle = ta.getInt(attr, 360);
            }
        }
        ta.recycle();

        if (backResId != 0) {
            mBackground = BitmapFactory.decodeResource(getResources(), backResId);
        }
        if (progressResId != 0) {
            mProgress = BitmapFactory.decodeResource(getResources(), progressResId);
        }

        initAnim();

        setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        mMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
        ;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.WHITE);
    }

    private void initAnim() {
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                animValue = mAnimator.getAnimatedFraction();
                invalidateView();
            }
        });
        mAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                animValue = 1.0f;
                invalidateView();
            }
        });
    }

    public void setProgress(float angle) {
        if (angle >= 0 && angle <= mTotleAngle && angle != mDstAngle) {
            mFromAngle = mDstAngle;
            mDstAngle = angle;
            if (Math.abs(mDstAngle - mFromAngle) > MIN_ANIM_OFFSET) {
                startAnim();
            } else {
                invalidate();
            }
        }
    }

    public int getMax() {
        return mTotleAngle;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int width;
        int height;
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            int w1 = (mBackground != null) ? mBackground.getWidth() : 0;
            int w2 = (mProgress != null) ? mProgress.getWidth() : 0;
            width = Math.max(w1, w2);
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            int h1 = (mBackground != null) ? mBackground.getHeight() : 0;
            int h2 = (mProgress != null) ? mProgress.getHeight() : 0;
            height = Math.max(h1, h2);
        }

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mBackground != null) {
            canvas.drawBitmap(mBackground, 0, 0, mPaint);
        }

        calculateValue();
        if (mProgress != null && mCurAngle > 0.01f) {
            int w = getWidth();
            int h = getHeight();
            @SuppressLint("WrongConstant")
            int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.MATRIX_SAVE_FLAG
                    | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
                    | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
            canvas.drawArc(0, 0, w, h, mStartAngle, mCurAngle, true, mPaint);
            mPaint.setXfermode(mMode);
            canvas.drawBitmap(mProgress, 0, 0, mPaint);
            mPaint.setXfermode(null);
            canvas.restoreToCount(layerId);
        }
    }

    private void calculateValue() {
        if (mDstAngle < mFromAngle) {
            mCurAngle = mFromAngle - (animValue * (mFromAngle - mDstAngle));
        } else if (mDstAngle > mFromAngle) {
            mCurAngle = (animValue * (mDstAngle - mFromAngle)) + mFromAngle;
        } else {
            mCurAngle = mDstAngle;
        }
//    	Log.d("RoundProgress", "calculateValue : " + mCurAngle);
    }

    private void startAnim() {
        if (mAnimator.isRunning()) {
            mAnimator.setCurrentFraction(0);
            mAnimator.setCurrentPlayTime(0);
            animValue = 0;
        } else {
            animValue = 0;
            mAnimator.setDuration(500);
            mAnimator.start();
        }
    }

    private void invalidateView() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            postInvalidateOnAnimation();
        } else {
            invalidate();
        }
    }
}
